// wave code mainly borrowed and adapted from the wave demo of Infantile Paralysiser
// C/objective-c link image buffer code borrowed and adapted from the iphonenes iphone project

#import <CoreSurface/CoreSurface.h>
#import <CoreGraphics/CGContext.h>
#import <CoreGraphics/CGBitmapContext.h>
#include "draw.h"
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/select.h>

extern void updateScreen();
extern int __screenOrientation;
extern int __x1;
extern int __y1;
extern int __x2;
extern int __y2;
extern int __height;
extern int __waveType;
extern int __waveSize;
extern int __waveSpeed;


extern pthread_cond_t screenUpdateLock;
extern pthread_mutex_t screenUpdateMutex;
extern PIXEL *m_cba;
extern CoreSurfaceBufferRef screenSurface;

char emuThread;

#define MAX_WAVE_SIZE (128)
static int waveRaiseTable[MAX_WAVE_SIZE*MAX_WAVE_SIZE];


#define waveWborder 1
#define waveHborder 1
#define waveWPborder 322
#define waveHPborder 482

int waveWidth;
int waveWidthBorders;
int waveHeight;
int waveHeightBorders;
int waveSize;


#define WAVEFILTER_MAXSIZE (waveWPborder*waveHPborder*2)

static int wave1[WAVEFILTER_MAXSIZE],wave2[WAVEFILTER_MAXSIZE],wave3[WAVEFILTER_MAXSIZE];
static int *pwave1,*pwave2,*pwave3;
static int *pfwave1,*pfwave2,*pfwave3;

//#define bgPad (((96*(320+192))+96)*sizeof(PIXEL))
//#define WAVESOURCESIZE ((480+192)*(320+192)*sizeof(PIXEL))
#define bgPad 0//(96*sizeof(PIXEL))
#define WAVESOURCESIZE ((480)*(320)*sizeof(PIXEL))
static int wavesourcesize = WAVESOURCESIZE;
static PIXEL wavesource[WAVESOURCESIZE];

static void waveInit(void)
{
 int idx;
 pfwave1=&wave1[0];
 pfwave2=&wave2[0];
 pfwave3=&wave3[0];
 pwave1=&wave1[waveWborder+waveWidthBorders];
 pwave2=&wave2[waveWborder+waveWidthBorders];
 pwave3=&wave3[waveWborder+waveWidthBorders];
 
 for(idx=0;idx<WAVEFILTER_MAXSIZE;idx++){
   pfwave1[idx]=0;
   pfwave2[idx]=0;
   pfwave3[idx]=0;
 }
}



static void waveRaiseTableInit(u32 type)
{
 int x,y;
 int *pwt=&waveRaiseTable[0];
 
 for(x=0;x<waveSize;x++){
   for(y=0;y<waveSize;y++){
     pwt[x+(y*waveSize)]=0;
   }
 }
 
 for(x=0;x<waveSize;x++){
   for(y=0;y<waveSize;y++){
     int r=(x*x)+(y*y);
     float l=sqrt(r);
     switch(type){
       case 0: { // smooth circle
         float sw=waveSize*16/16;
         if(((waveSize-sw)<l)&&(l<waveSize)){
           float h=sin((l-sw)/sw*3.14159)*1*65536;
           pwt[x+(y*waveSize)]=(int)h;
         }
       } break;
       case 1: { // sharp circle
         float sw=waveSize*4/16;
         if(((waveSize-sw)<l)&&(l<waveSize)){
           float h=sin((l-sw)/sw*3.14159)*1*65536;
           pwt[x+(y*waveSize)]=(int)h;
         }
       } break;
       case 2: { // sine ball
         if(l<waveSize){
           float h=sin((l/waveSize*3.14159/2))*1*65536;
           pwt[x+(y*waveSize)]=(int)h;
         }
       } break;
       case 3: { // cosine ball
         if(l<waveSize){
           float h=cos((l/waveSize*3.14159/2))*1*65536;
           pwt[x+(y*waveSize)]=(int)h;
         }
       } break;
     }
   }
 }
}

static void waveRaise(int cx,int cy,int ch)
{
       int x,y;
       int *pw2=pwave2;
       int *pwt=&waveRaiseTable[0];
       int tmpval = 65536<<2;
       int tmpval2 = (-tmpval-1);
       int absx;
       int waveHeight_1 = (waveHeight-1);
       int inity = -waveSize+1;
       for(x=-waveSize+1;x<waveSize;x++){
               int px=cx+x;
               if ((1<=px)&&(px<(waveWidth-1))){
                       absx = abs(x);
                       for(y=inity;y<waveSize;y++){
                               int py=cy+y;
                               if ((1<=py)&&(py<waveHeight_1)){
                                       int h=pwt[absx+(abs(y)*waveSize)];
                                       if(h!=0){
                                               h=h*ch>>8;
                                               int tmp;
                                               int idx = px+(py*waveWPborder);
                                               tmp=h+pw2[idx];
                                               if(tmpval<tmp) pw2[idx]=tmpval;
                                               else if(tmp<tmpval2) pw2[idx]=tmpval2;
                                               else pw2[idx]=tmp;
                                       }
                               }
                       }
               }
       }
}

#define bgwidth 512
/*
static void waveCalcDraw(PIXEL *buf,PIXEL *bgbuf)
{
	int h,x,y,t;
	int *pwavet;
	int *pw1=pwave1;
	int *pw2=pwave2;
	int *pw3=pwave3;

	int chk1 = wavesource-bgbuf;
	int chk2 = wavesource+wavesourcesize-bgbuf;

	for(y=(waveHeight-1);y>=0;y--){
		for(x=(waveWidth-1);x>=0;x--){
			t=pw1[x];
			pw3[x]=((((pw2[x-waveWidthBorders]+pw2[x+waveWidthBorders]+pw2[x-1]+pw2[x+1])>>1)-t)*63)>>6;
			h=t>>11;
			h=x+h+(h<<9);
            buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h]; // consistancy check
		}
		pw1+=waveWidthBorders; pw2+=waveWidthBorders; pw3+=waveWidthBorders;
		buf+=320;
		bgbuf+=bgwidth;
		chk1 -= bgwidth;
		chk2 -= bgwidth;
	}


	pwavet=pwave1;
	pwave1=pwave2;
	pwave2=pwave3;
	pwave3=pwavet;
}

*/
static int initx;
static int inity;
static int ida_base;
static int idb_base;
static int idc_base;
static int idd_base;

static void waveCalcDrawMedium(PIXEL *buf,PIXEL *bgbuf)
{

       int h,x,y,t;
       int *pwavet;
       int *pw1=pwave1;
       int *pw2=pwave2;
       int *pw3=pwave3;
       int chk1,chk2;
       int ida,idb,idd;
       int Sx;
       int va,vb,vc,vd,vt;
	   int add1=320+1;
	   int add2=bgwidth+1;
	   int add3=320<<1;
	   int add4=bgwidth<<1;
       chk1 = wavesource-bgbuf;
       chk2 = wavesource+wavesourcesize-bgbuf;

       for(y=inity;y>=0;y--){
               ida=ida_base;
               idb=idb_base;
               idd=idd_base;
               va = pw2[ida];
               vb = pw2[idb];
               vc = pw2[idc_base];
               vt = pw2[initx];
               vd = pw2[idd];
               for(x=initx;x>=0;){
					t=pw1[x];
					pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;
					Sx = (x<<1)+1;
					h=t>>11;
					h=Sx+h+(h<<9);
					if ((h<chk1) || (h>chk2)){ // consistancy check
						buf[Sx--]=0;
						buf[Sx]=0;
						Sx+=add1;
						buf[Sx--]=0;
						buf[Sx]=0;
					}
					else{
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
						Sx+=add1;h+=add2;
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
					}
					x--;
					va = pw2[--ida];
					vb = pw2[--idb];
					vc = vt;
					vt = vd;
					vd = pw2[--idd];
				}
               pw1+=waveWPborder; pw2+=waveWPborder; pw3+=waveWPborder;
               buf+=add3;
               bgbuf+=add4;
               chk1 -= add4;
               chk2 -= add4;
       }


       pwavet=pwave1;
       pwave1=pwave2;
       pwave2=pwave3;
       pwave3=pwavet;
}

static void waveCalcDrawQuick(PIXEL *buf,PIXEL *bgbuf)
{

       int h,x,y,t;
       int *pwavet;
       int *pw1=pwave1;
       int *pw2=pwave2;
       int *pw3=pwave3;
       int chk1,chk2;
       int ida,idb,idd;
       int Sx;
       int va,vb,vc,vd,vt;
	   int add1=320+3;
	   int add2=bgwidth+3;
	   int add3=320<<2;
	   int add4=bgwidth<<2;
       chk1 = wavesource-bgbuf;
       chk2 = wavesource+wavesourcesize-bgbuf;

       for(y=inity;y>=0;y--){
               ida=ida_base;
               idb=idb_base;
               idd=idd_base;
               va = pw2[ida];
               vb = pw2[idb];
               vc = pw2[idc_base];
               vt = pw2[initx];
               vd = pw2[idd];
               for(x=initx;x>=0;){
					t=pw1[x];
					pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;
					Sx = (x<<2)+3;
					h=t>>11;
					h=Sx+h+(h<<9);
					if ((h<chk1) || (h>chk2)){ // consistancy check
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx]=0;
						Sx+=add1;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx]=0;
						Sx+=add1;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx]=0;
						Sx+=add1;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx--]=0;
						buf[Sx]=0;
					}
					else{
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
						Sx+=add1;h+=add2;
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
						Sx+=add1;h+=add2;
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
						Sx+=add1;h+=add2;
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx--]=bgbuf[h--];
						buf[Sx]=bgbuf[h];
					}
					x--;
					va = pw2[--ida];
					vb = pw2[--idb];
					vc = vt;
					vt = vd;
					vd = pw2[--idd];
				}
               pw1+=waveWPborder; pw2+=waveWPborder; pw3+=waveWPborder;
               buf+=add3;
               bgbuf+=add4;
               chk1 -= add4;
               chk2 -= add4;
       }


       pwavet=pwave1;
       pwave1=pwave2;
       pwave2=pwave3;
       pwave3=pwavet;
}


static void waveCalcDraw(PIXEL *buf,PIXEL *bgbuf)
{

       int h,x,y,t;
       int *pwavet;
       int *pw1=pwave1;
       int *pw2=pwave2;
       int *pw3=pwave3;
       int chk1,chk2;
       int ida,idb,idd;
       
       int va,vb,vc,vd,vt;
       chk1 = wavesource-bgbuf;
       chk2 = wavesource+wavesourcesize-bgbuf;


       for(y=inity;y>=0;y--){
               ida=ida_base;
               idb=idb_base;
               idd=idd_base;
               va = pw2[ida];
               vb = pw2[idb];
               vc = pw2[idc_base];
               vt = pw2[initx];
               vd = pw2[idd];
               for(x=initx;x>=0;){
					// t=pw1[x];
					// pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;
					// h=t>>11;
					// h=x+h+(h<<9);
					// buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h]; // consistancy check
					// x--;
					// va = pw2[--ida];
					// vb = pw2[--idb];
					// vc = vt;
					// vt = vd;
					// vd = pw2[--idd];

					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];
					t=pw1[x];pw3[x]=((((va+vb+vc+vd)>>1)-t)*63)>>6;h=t>>11;h=x+h+(h<<9);buf[x]=((h<chk1) || (h>chk2))?0:bgbuf[h];x--;va = pw2[--ida];vb = pw2[--idb];vc = vt;vt = vd;vd = pw2[--idd];

					}
               pw1+=waveWPborder; pw2+=waveWPborder; pw3+=waveWPborder;
               buf+=320;
               bgbuf+=bgwidth;
               chk1 -= bgwidth;
               chk2 -= bgwidth;
       }


       pwavet=pwave1;
       pwave1=pwave2;
       pwave2=pwave3;
       pwave3=pwavet;
}

#undef bgwidth


static u32 spec_curtype;
#define spec_curtypecount (5)

static void setspec(u32 type)
{
 spec_curtype=type;
 /*
 const char *pstr;
 
 switch(spec_curtype){
   case 0: pstr="Normal"; break;
   case 1: pstr="Red   "; break;
   case 2: pstr="Green "; break;
   case 3: pstr="Blue  "; break;
   case 4: pstr="OFF   "; break;
   default: pstr="ERROR!"; break;
 }
 
 _consolePrintSet(0,10+0);
 _consolePrintf("A button. Specular Type : %s",pstr);
 */
}

static bool showtexturemap;

static void setshowtexturemap(bool visible)
{
 showtexturemap=visible;
 /*
 const char *pstr;
 
 if(showtexturemap==false){
   pstr="OFF";
   }else{
   pstr="ON ";
 }
 
 _consolePrintSet(0,10+2);
 _consolePrintf("B button. Show Texture Map : %s",pstr);
 */
}



/*
int line = 0;
void generateImage(PIXEL *c) {
  int x, y, i = 0;
  WORD wColor;
   for (y=0; y < waveHeight; y++)
       {
               for (x=0; x<waveWidth; x++) {
                       if ((0 == (y%20)) || (0 == (x%20)) || (0 == ((y+1)%20)) || (0 == ((x+1)%20))){
                               wColor = RGBd(0,0,0);
                       }
                       else{
                               wColor = RGBd(0,(x/20),(y/20));
                       }
                       c[i++] = wColor;
               }
       }
}
*/


CGContextRef CreateARGBBitmapContext (CGImageRef inImage)
{
   CGContextRef    context = NULL;
   CGColorSpaceRef colorSpace;
   void *          bitmapData;
   int             bitmapByteCount;
   int             bitmapBytesPerRow;

    // Get image width, height. We'll use the entire image.
   size_t pixelsWide = CGImageGetWidth(inImage);
   size_t pixelsHigh = CGImageGetHeight(inImage);

   // Declare the number of bytes per row. Each pixel in the bitmap in this
   // example is represented by 4 bytes; 8 bits each of red, green, blue, and
   // alpha.
   bitmapBytesPerRow   = (pixelsWide * 4);
   bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

   // Use the generic RGB color space.
   colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
   if (colorSpace == NULL)
   {
       fprintf(stderr, "Error allocating color space\n");
       return NULL;
   }

   // Allocate memory for image data. This is the destination in memory
   // where any drawing to the bitmap context will be rendered.
   bitmapData = malloc( bitmapByteCount );
   if (bitmapData == NULL)
   {
       fprintf (stderr, "Memory not allocated!");
       CGColorSpaceRelease( colorSpace );
       return NULL;
   }

   // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
   // per component. Regardless of what the source image format is
   // (CMYK, Grayscale, and so on) it will be converted over to the format
   // specified here by CGBitmapContextCreate.
   context = CGBitmapContextCreate (bitmapData,
                                   pixelsWide,
                                   pixelsHigh,
                                   8,      // bits per component
                                   bitmapBytesPerRow,
                                   colorSpace,
                                   kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
   if (context == NULL)
   {
       free (bitmapData);
       fprintf (stderr, "Context not created!");
   }


   // Make sure and release colorspace before returning
   CGColorSpaceRelease( colorSpace );

   return context;
}


void ManipulateImagePixelData(CGImageRef inImage,PIXEL *bgbuf)
{
   // Create the bitmap context
   CGContextRef cgctx = CreateARGBBitmapContext(inImage);
   if (cgctx == NULL)
   {
       // error creating context
       return;
   }

    // Get image width, height. We'll use the entire image.
   size_t w = CGImageGetWidth(inImage);
   size_t h = CGImageGetHeight(inImage);
   CGRect rect = {{0,0},{w,h}};

   // Draw the image to the bitmap context. Once we draw, the memory
   // allocated for the context for rendering will then contain the
   // raw image data in the specified color space.
   CGContextDrawImage(cgctx, rect, inImage);

   // Now we can get a pointer to the image data associated with the bitmap
   // context.
   PIXEL* data = (PIXEL*) CGBitmapContextGetData (cgctx);
       
       // quick Image Copy
       pthread_mutex_lock(&screenUpdateMutex);
       memcpy (m_cba, data, sizeof(PIXEL)*w*h);
       pthread_mutex_unlock(&screenUpdateMutex);
       
   int x, y, i = 0;
       for (y=0; y < 480; y++) {
               for (x=0; x<320; x++) {
                       bgbuf[x+(y<<9)] = data[i++];
               }
       }

/*      int r,g,b;
       WORD wColor;
           //b = (u8)(((data[i] & 0xFF000000)>>24)*31/255);
           //b = (((data[i] & 0xFF000000)>>24)*31/255);
           //g = (((data[i] & 0x00FF0000)>>16)*63/255);
           //r = (((data[i] & 0x0000FF00)>>8)*31/255);

          // r = ((((data[i]>>2) & 0x3FF))*31/1023);
          // g = ((((data[i]>>2) & 0xFFC00)>>10)*31/1023);
          // b = ((((data[i]>>2) & 0x3FF00000)>>20)*31/1023);

                       // 0x3FF : 10
                       // 0xFFC00 : 20
                       // 0x3FF00000 : 30
           //b = (((data[i] & 0x000000FF))*31/255);
           //wColor = ((wColor & 0x7fe0)<<1) | (wColor&0x001f);
                       //bgbuf[i] = RGBd(r,g,b);;
                       //i++;
                       */
       
   // When finished, release the context
   CGContextRelease(cgctx);
   // Free image data memory for the context
   if (data)
   {
       free(data);
   }

}

void prepareImage(CGImageRef sourceImage){
	ManipulateImagePixelData(sourceImage,wavesource+bgPad);
}
void PlaySlow(){
	waveWidth = 320;
	waveHeight = 480;
	waveSize = __waveSize;
	waveWidthBorders  = (waveWidth+(2*waveWborder));
	waveHeightBorders = (waveHeight+(2*waveHborder));
	waveInit();
	setspec(0);
	setshowtexturemap(true);
	waveRaiseTableInit(__waveType);

	initx=(waveWidth-1);
	inity=(waveHeight-1);
	ida_base = initx+waveWPborder;
	idb_base = initx-waveWPborder;
	idc_base = initx+1;
	idd_base = initx-1;

	// Main loop
	while (emuThread)
	{
	if ((__x2 >= 0) && (__y2 >= 0)){
		   waveRaise(__x2,__y2,-__height);
	}
	if ((__x1 >= 0) && (__y1 >= 0)){
		   waveRaise(__x1,__y1,-__height);
	}
	pthread_mutex_lock(&screenUpdateMutex);
	waveCalcDraw(m_cba,wavesource+bgPad);
	pthread_mutex_unlock(&screenUpdateMutex);
	updateScreen();
	}
}
void PlayMedium(){
	waveWidth = 320>>1;
	waveHeight = 480>>1;
	waveSize = __waveSize>>1;
	waveWidthBorders  = (waveWidth+(2*waveWborder));
	waveHeightBorders = (waveHeight+(2*waveHborder));
	waveInit();
	setspec(0);
	setshowtexturemap(true);
	waveRaiseTableInit(__waveType);

	initx=(waveWidth-1);
	inity=(waveHeight-1);
	ida_base = initx+waveWPborder;
	idb_base = initx-waveWPborder;
	idc_base = initx+1;
	idd_base = initx-1;

	// Main loop
	while (emuThread)
	{
	if ((__x2 >= 0) && (__y2 >= 0)){
		   waveRaise(__x2>>1,__y2>>1,-__height);
	}
	if ((__x1 >= 0) && (__y1 >= 0)){
		   waveRaise(__x1>>1,__y1>>1,-__height);
	}
	pthread_mutex_lock(&screenUpdateMutex);
	waveCalcDrawMedium(m_cba,wavesource+bgPad);
	pthread_mutex_unlock(&screenUpdateMutex);
	updateScreen();
	}
}
void PlayQuick(){
	waveWidth = 320>>2;
	waveHeight = 480>>2;
	waveSize = __waveSize>>2;
	waveWidthBorders  = (waveWidth+(2*waveWborder));
	waveHeightBorders = (waveHeight+(2*waveHborder));
	waveInit();
	setspec(0);
	setshowtexturemap(true);
	waveRaiseTableInit(__waveType);

	initx=(waveWidth-1);
	inity=(waveHeight-1);
	ida_base = initx+waveWPborder;
	idb_base = initx-waveWPborder;
	idc_base = initx+1;
	idd_base = initx-1;

	// Main loop
	while (emuThread)
	{
	if ((__x2 >= 0) && (__y2 >= 0)){
		   waveRaise(__x2>>2,__y2>>2,-__height);
	}
	if ((__x1 >= 0) && (__y1 >= 0)){
		   waveRaise(__x1>>2,__y1>>2,-__height);
	}
	pthread_mutex_lock(&screenUpdateMutex);
	waveCalcDrawQuick(m_cba,wavesource+bgPad);
	pthread_mutex_unlock(&screenUpdateMutex);
	updateScreen();
	}
}
void *emulation_thread(void *args) {
		switch (__waveSpeed){
			case 0 : PlaySlow();break;
			case 1 : PlayMedium();break;
			case 2 : PlayQuick();break;
		}
       return NULL;
}
